package com.nageoffer.jobtrain.projects.job;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.nageoffer.jobtrain.projects.dao.entity.ContestDO;
import com.nageoffer.jobtrain.projects.dao.entity.MessageDO;
import com.nageoffer.jobtrain.projects.dao.mapper.ContestAnswerMapper;
import com.nageoffer.jobtrain.projects.dao.mapper.ContestMapper;
import com.nageoffer.jobtrain.projects.dao.mapper.MessageMapper;
import com.nageoffer.jobtrain.projects.service.handler.contest.dto.ContestUserScoreDTO;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 竞赛结束结果统计处理类 -XXL-Job处理器
 * author：唐晨
 */
@Component
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "xxl-job", name = "enabled", havingValue = "true", matchIfMissing = true)
public class ContestStatsResultHandler extends IJobHandler {
    private final ContestMapper contestMapper;
    private final ContestAnswerMapper contestAnswerMapper;
    private final MessageMapper messageMapper;

    /**
     * 竞赛结束结构统计执行函数
     */
    @XxlJob(value = "jobTrainContestStatsResult")
    public void execute() throws Exception {
        // 统计结束时间，在前一天 - now（0:00）的竞赛
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime todayStart = now.toLocalDate().atStartOfDay();
        // 前一天的时间范围
        LocalDateTime yesterdayStart = todayStart.minusDays(1); // 前一天 0:00
        LocalDateTime yesterdayEnd = todayStart.minusNanos(1);  // 昨日结束（今日 0:00 的前 1 纳秒）
        // 转换为 Date 类型
        Date startDate = Date.from(yesterdayStart.atZone(ZoneId.systemDefault()).toInstant());
        Date endDate = Date.from(yesterdayEnd.atZone(ZoneId.systemDefault()).toInstant());
        LambdaQueryWrapper<ContestDO> queryWrapper = Wrappers.lambdaQuery(ContestDO.class)
                .select(ContestDO::getId, ContestDO::getTitle)
                .eq(ContestDO::getStatus, 1)
                .ge(ContestDO::getEndTime, startDate)
                .le(ContestDO::getEndTime, endDate);
        List<ContestDO> contestList = contestMapper.selectList(queryWrapper);
        if (CollectionUtil.isEmpty(contestList)) {
            return;
        }
        // 将前一天结束的竞赛将ID全部获取出来
        List<Long> contestIdList = contestList.stream()
                .map(ContestDO::getId)
                .collect(Collectors.toList());
        List<ContestUserScoreDTO> contestUserScoreList = contestAnswerMapper.selectUserScoreByContest(contestIdList);
        // 再根据这个列表，根据竞赛ID，再进行分出每个竞赛中，不同用户的成绩列表
        Map<Long, List<ContestUserScoreDTO>> contestUserScoreMap = contestUserScoreList.stream().collect(Collectors.groupingBy(ContestUserScoreDTO::getContestId));
        handlerCreateContestStatsMessage(contestList, contestUserScoreMap);
    }

    private void handlerCreateContestStatsMessage(List<ContestDO> contestList, Map<Long, List<ContestUserScoreDTO>> contestUserScoreMap) {
        // 获取出每个竞赛，各个参与竞赛用户的结果消息
        List<MessageDO> messageList = new ArrayList<>();
        for (ContestDO contest : contestList) {
            Long contestId = contest.getId();
            List<ContestUserScoreDTO> contestUserScoreList = contestUserScoreMap.get(contestId);
            // 获取这个竞赛总参数的人数
            int totalUserSize = contestUserScoreList.size();
            int rank = 1;
            for (ContestUserScoreDTO contestUserScore : contestUserScoreList) {
                String messageTitle = contest.getTitle() + "- 结果排名情况";
                String messageContest = "您所参与的竞赛：" + contest.getTitle() + "，本次竞赛共" + totalUserSize + "人参与，"
                        + "您本次竞赛的排名为：" + rank + "名，总成绩为：" + contestUserScore.getTotalScores() + "分！";
                // 系统消息记录结构
                MessageDO messageDO = MessageDO.builder()
                        .title(messageTitle)
                        .content(messageContest)
                        .receive(contestUserScore.getPhoneNumber())
                        .build();
                messageList.add(messageDO);
                rank++;
            }
        }
        // 进行批量消息插入
        messageMapper.insert(messageList, messageList.size());
    }
}
